package com.ungao.framework.parse.xml;

import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class XpathXmlConfigParser implements XmlConfigParser {

    private DocumentBuilderFactory documentBuilderFactory;
    private DocumentBuilder documentBuilder;
    private Document document;
    private Map<String, NodeList> nodeLists = new ConcurrentHashMap<>();

    public XpathXmlConfigParser() {
        try {
            this.documentBuilderFactory = DocumentBuilderFactory.newInstance();
            this.documentBuilder = documentBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
    }

    @Override
    public XpathXmlConfigParser load(InputStream inputStream) throws Exception {
        this.document = this.documentBuilder.parse(inputStream);
        document.getDocumentElement().normalize();
        return this;
    }

    @Override
    public List<?> getList(String expression, String attributeName) throws Exception {
        if (this.nodeLists.containsKey(expression)) {
            return this.get(this.nodeLists.get(expression), attributeName);
        }
        XPath xPath = XPathFactory.newInstance().newXPath();
        NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
        this.nodeLists.putIfAbsent(expression, nodeList);
        return this.get(nodeList, attributeName);
    }

    @Override
    public String getOne(String expression, String attributeName) throws Exception {
        List<?> result = this.getList(expression, attributeName);
        if (result == null || result.size() == 0) {
            return null;
        }
        return String.valueOf(result.get(0));
    }

    public List<?> get(NodeList nodeList, String attributeName) {
        for (int i = 0, length = nodeList.getLength(); i < length; i++) {
            Node node = nodeList.item(i);
            Element element = (Element) node;
            NodeList tagNameChildList = element.getElementsByTagName(attributeName);
            System.out.println(element.getAttribute("value"));
            if (tagNameChildList != null && tagNameChildList.getLength() > 0) {
                return Arrays.asList(tagNameChildList.item(0).getTextContent());
            }
        }
        return null;
    }
}
